from system.object import Object
from system.eventServer import eventServer
from system.dynload import dynload

import yaml
import time
import sys
import os.path

class GameServer:
    def __init__(self):
        self.plugins = {}
        self.interfaces = {}
        self.shutdown = False
        self.timeToRun = -1
        self.frameLimit = 60
        self.screenw = 800
        self.screenh = 600
        self.fullscreen = False
        self.server = True
        self.ip = None
        self.port = None
        self.serverAddress = None
        self.serverPort = None
        self.windowTitle = "Shudai"
        self.fixedFrames = 0
        self.time = 0
        
        eventServer.register("shutdown",self.doShutdown)
        
    def loadConfig(self, filename = None):
        if not filename:
            if len(sys.argv) > 1 and os.path.isfile(sys.argv[1]):
                filename = sys.argv[1]
            else:
                filename = "dat/config.yml"
            
        try:
            data = yaml.evalLoad(open(filename,"r"))
        except:
            return False
        
        data.update(self.buildSysArgs())
        
        for key, val in data.iteritems():
            funcName = 'load_%s' % key
            if hasattr(self,funcName) and callable(getattr(self,funcName)):
                getattr(self,funcName)(key,val)
            else:
                self.__dict__[key] = val
                
    def buildSysArgs(self):
        data = {}
        
        for i, arg in enumerate(sys.argv[1:]):
            if arg.startswith('+'):
                data[arg[1:]] = True
            elif arg.startswith('-'):
                data[arg[1:]] = False
            elif '=' in arg:
                pos = arg.find('=')
                name = arg[:pos]
                val = arg[pos+1:]
                try:
                    data[name] = eval(val)
                except:
                    data[name] = val
            elif arg == '=' and i > 0 and i < len(sys.argv) - 1:
                name = sys.argv[i]
                val = sys.argv[i+2]
                try:
                    data[name] = eval(val)
                except:
                    data[name] = val
                    
        return data
                
    def load_plugins(self, key, data):
        for name in data:
            if not self.plugins.has_key(name):
                pluginClass = dynload(name)
                if pluginClass:
                    self.plugins[name] = pluginClass()
                    print "loaded plugin", name
            
    def run(self):
        self.loadConfig()
        
        from system.networkServer import networkServer
        networkServer.init(self.server,self.ip,self.port,self.serverAddress,self.serverPort)
        
        self.root = Object(None,"root")
        
        frameTime = 1.0 / float(self.frameLimit)
        
        lastTime = self.time = startTime = time.time()
        renderTime = self.time + frameTime
        
        updateCount = renderCount = 0
        
        if self.fixedFrames:
            self.time = 0
            frameTime = 1.0 / float(self.fixedFrames)
            while not self.shutdown and (self.timeToRun < 0 or self.time < self.timeToRun):
                self.time += frameTime
                eventServer.pull("update",{"time":self.time,"dtime":frameTime})
                eventServer.pull("render",{"time":self.time,"dtime":frameTime})
            
        else:
            while not self.shutdown and (self.timeToRun < 0 or self.time - startTime < self.timeToRun):
                updateCount += 1
                
                self.time = time.time()
                dtime = self.time - lastTime
                lastTime = self.time
                assert lastTime >= 0.0
                
                eventServer.pull("update",{"time":self.time,"dtime":dtime})
                
                if self.time >= renderTime:
                    renderCount += 1
                    renderTime += frameTime
                    
                    eventServer.pull("render",{"time":self.time,"dtime":dtime})
                
            totalTime = time.time() - startTime
            
            print "%d updates and %d renders = %f updates per render" % (updateCount,renderCount,float(updateCount)/float(renderCount))
            print "%d frames in %f seconds = %f fps" % (updateCount,totalTime,float(updateCount)/totalTime)
        
        eventServer.pull("shutdownPlugins",{})
        networkServer.destroy()
        
    def doShutdown(self, cmd, args):
        self.shutdown = True
                
gameServer = GameServer()
gameServer.run()
